In [ ]:
# Bibliotecas

import yfinance as yf
import pandas as pd
import plotly.graph_objects as go
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.cluster import KMeans
from math import sqrt

Carteira de Fundos de Investimento Imobiliário¶

A carteira é composta dos fundos mais rentáveis do primeiro semestre de 2023 de acordo com o Estadão e dos fundos presentes em duas carteiras sugeridas pelo Banco do Brasil para setembro de 2023.
https://einvestidor.estadao.com.br/mercado/fundos-imobiliarios-mais-rentaveis-selic-investimentos/ https://www.bb.com.br/docs/portal/upb/CarteiraFII.pdf

In [ ]:
# Fundos mais rentáveis do primeiro semestre de 2023

fii_mais_rentaveis = ['MGHT11.SA', 'KIVO11.SA', 'KNRE11.SA', 'HABT11.SA', 'VOTS11.SA', 'JPPA11.SA', 'RBOP11.SA', 'URPR11.SA', 'RZAK11.SA']

# Cotação do ano de 2023 até o momento
data_inicio = "2023-01-01"
data_fim = "2023-10-02"

# Baixar as cotações dos ativos
for i, ativo in enumerate(fii_mais_rentaveis):
    data = yf.download(ativo, start=data_inicio, end=data_fim)

    plt.figure(figsize=(12, 6))
    plt.plot(data['Adj Close'], label=ativo)
    plt.title(f"Cotação de {ativo} em 2023", fontsize=16)
    plt.xlabel("Data",fontsize=13)
    plt.ylabel("Preço de Fechamento Ajustado", fontsize=13)
    plt.xticks(fontsize=13)
    plt.yticks(fontsize=13)
    plt.grid(True)
    plt.show()
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
In [ ]:
carteira_fii_renda = ['KFOF11.SA', 'XPSF11.SA', 'HGCR11.SA', 'PLCR11.SA', 'RECR11.SA', 'VGIP11.SA', 'MFII11.SA', 'TGAR11.SA']

# Cotação do ano de 2023 até o momento
data_inicio = "2023-01-01"
data_fim = "2023-10-02"

# Baixar as cotações dos ativos
for i, ativo in enumerate(carteira_fii_renda):
    data = yf.download(ativo, start=data_inicio, end=data_fim)

    plt.figure(figsize=(12, 6))
    plt.plot(data['Adj Close'], label=ativo)
    plt.title(f"Cotação de {ativo} em 2023", fontsize=16)
    plt.xlabel("Data",fontsize=13)
    plt.ylabel("Preço de Fechamento Ajustado", fontsize=13)
    plt.xticks(fontsize=13)
    plt.yticks(fontsize=13)
    plt.grid(True)
    plt.show()
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
In [ ]:
carteira_fii_ganho = ['RZTR11.SA', 'JSRE11.SA', 'PVBI11.SA', 'RBRF11.SA', 'BRCO11.SA', 'RBRL11.SA', 'HGBS11.SA']

# Cotação do ano de 2023 até o momento
data_inicio = "2023-01-01"
data_fim = "2023-10-02"

# Baixar as cotações dos ativos
for i, ativo in enumerate(carteira_fii_ganho):
    data = yf.download(ativo, start=data_inicio, end=data_fim)

    plt.figure(figsize=(12, 6))
    plt.plot(data['Adj Close'], label=ativo)
    plt.title(f"Cotação de {ativo} em 2023", fontsize=16)
    plt.xlabel("Data",fontsize=13)
    plt.ylabel("Preço de Fechamento Ajustado", fontsize=13)
    plt.xticks(fontsize=13)
    plt.yticks(fontsize=13)
    plt.grid(True)
    plt.show()
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
[*********************100%***********************]  1 of 1 completed
No description has been provided for this image
In [ ]:
# Conjunto com todos os ativos sem repetição
ativos = set(fii_mais_rentaveis + carteira_fii_renda + carteira_fii_ganho)
# Converte o conjunto em uma lista
ativos = list(ativos)
print(ativos)
['RBRF11.SA', 'PLCR11.SA', 'MGHT11.SA', 'KIVO11.SA', 'RZTR11.SA', 'JPPA11.SA', 'MFII11.SA', 'RBOP11.SA', 'HABT11.SA', 'RBRL11.SA', 'VOTS11.SA', 'RZAK11.SA', 'KNRE11.SA', 'HGBS11.SA', 'KFOF11.SA', 'JSRE11.SA', 'PVBI11.SA', 'XPSF11.SA', 'RECR11.SA', 'URPR11.SA', 'BRCO11.SA', 'HGCR11.SA', 'VGIP11.SA', 'TGAR11.SA']
In [ ]:
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

# Dicionário para armazenar os indicadores de cada ativo
indicadores_por_ativo = {}

for ativo in ativos:
    estoque = yf.Ticker(ativo)
    informacoes = estoque.info

    indicadores = {
    'P/L (Relação Preço-Lucro)': informacoes.get('trailingPE', None),
    'Dividend Yield (Rendimento de Dividendo)': informacoes.get('dividendYield', None),
    'Cap. de Mercado': informacoes.get('marketCap', None),
    'Volume Médio': informacoes.get('averageVolume', None)
    }


    def formatar_valor(valor, tipo='moeda'):
        if valor is None:
            return None
        if tipo == 'moeda':
            return f"R$ {valor:,.2f}"
        elif tipo == 'porcentagem':
            return f"{valor * 100:.2f}%"

    for chave in indicadores:
        if "Yield" in chave :
            indicadores[chave] = formatar_valor(indicadores[chave], 'porcentagem')
        elif "Cap. de Mercado" in chave:
            indicadores[chave] = formatar_valor(indicadores[chave], 'moeda')

    indicadores_por_ativo[ativo] = indicadores

# Criar DataFrame
dfs = []
for ativo, indicadores in indicadores_por_ativo.items():
    df = pd.DataFrame(list(indicadores.items()), columns=['Indicador', 'Valor'])
    df['Ativo'] = ativo
    dfs.append(df)

resultado_df = pd.concat(dfs, ignore_index=True)

print(resultado_df)
                                   Indicador    Valor      Ativo
0                  P/L (Relação Preço-Lucro)     None  VGIP11.SA
1   Dividend Yield (Rendimento de Dividendo)    8.68%  VGIP11.SA
2                            Cap. de Mercado     None  VGIP11.SA
3                               Volume Médio    22999  VGIP11.SA
4                  P/L (Relação Preço-Lucro)    40.92  RBRF11.SA
..                                       ...      ...        ...
91                              Volume Médio    17074  KNRE11.SA
92                 P/L (Relação Preço-Lucro)      NaN  URPR11.SA
93  Dividend Yield (Rendimento de Dividendo)      NaN  URPR11.SA
94                           Cap. de Mercado      NaN  URPR11.SA
95                              Volume Médio  22982.0  URPR11.SA

[96 rows x 3 columns]
In [ ]:
resultado = resultado_df.pivot(index=['Indicador'], columns=['Ativo'], values='Valor').fillna('N/A')
resultado
Out[ ]:
Ativo BRCO11.SA HABT11.SA HGBS11.SA HGCR11.SA JPPA11.SA JSRE11.SA KFOF11.SA KIVO11.SA KNRE11.SA MFII11.SA ... RBRF11.SA RBRL11.SA RECR11.SA RZAK11.SA RZTR11.SA TGAR11.SA URPR11.SA VGIP11.SA VOTS11.SA XPSF11.SA
Indicador
Cap. de Mercado N/A R$ 380,305,024.00 R$ 2,292,574,720.00 R$ 1,632,622,592.00 N/A R$ 1,581,637,632.00 N/A N/A N/A R$ 387,944,832.00 ... R$ 1,119,636,608.00 R$ 613,201,536.00 R$ 2,307,029,504.00 N/A N/A N/A N/A N/A N/A N/A
Dividend Yield (Rendimento de Dividendo) 8.39% 14.61% 10.35% 12.27% 13.98% 7.26% 9.63% N/A 235.27% 13.66% ... 8.19% 8.49% 8.24% N/A N/A N/A N/A 8.68% 10.78% 10.60%
P/L (Relação Preço-Lucro) N/A N/A 9.966072 N/A N/A 12.264091 N/A N/A N/A 7.955745 ... 40.92 13.957381 7.252702 N/A N/A N/A N/A N/A N/A N/A
Volume Médio 27358 13870 22233 37753 2782 39365 15577 2404.0 17074 5314 ... 40049 12565 60364 48364.0 22414.0 34291.0 22982.0 22999 74 78513

4 rows × 24 columns

Candlestick¶

In [ ]:
fig = go.Figure(data=[go.Candlestick(x=df.index,
                open=df['Open'],
                high=df['High'],
                low=df['Low'],
                close=df['Close'])])

fig.update_layout(title=f'Gráfico de Candlestick para {ativo}')
fig.update_xaxes(
        tickangle=-45,  # Ângulo de rotação dos rótulos para melhor legibilidade
        dtick='M1',  # Exibe rótulos de data mensais
        tickformat='%Y-%m'  # Formato da data
    )
fig.show()

Candlestick de alta (bullish): O preço de abertura é inferior ao preço de fechamento. O corpo é representado de forma sólida na cor verde e indica pressão de compra.

Candlestick de baixa (bearish): O preço de abertura é superior ao preço de fechamento. corpo é representado de forma sólida na cor vermelha e indica pressão de compra.

In [ ]:
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

resultados_candles = []

for ativo in ativos:
    df = yf.download(ativo, start='2023-09-01', end='2023-10-02')

    ultimo_candlestick = 'Alta' if df['Close'].iloc[-1] > df['Open'].iloc[-1] else 'Baixa'

    resultados_candles.append({'Ativo': ativo, 'Último Candlestick': ultimo_candlestick})

df_candles = pd.DataFrame(resultados_candles)
print(df_candles)
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
        Ativo Último Candlestick
0   VGIP11.SA              Baixa
1   RBRF11.SA               Alta
2   KFOF11.SA               Alta
3   PVBI11.SA               Alta
4   MFII11.SA               Alta
5   HGCR11.SA               Alta
6   RBOP11.SA              Baixa
7   HABT11.SA               Alta
8   TGAR11.SA               Alta
9   MGHT11.SA              Baixa
10  RECR11.SA               Alta
11  PLCR11.SA               Alta
12  KIVO11.SA              Baixa
13  HGBS11.SA               Alta
14  JPPA11.SA               Alta
15  VOTS11.SA              Baixa
16  XPSF11.SA              Baixa
17  RBRL11.SA              Baixa
18  BRCO11.SA               Alta
19  RZTR11.SA               Alta
20  JSRE11.SA               Alta
21  RZAK11.SA               Alta
22  KNRE11.SA              Baixa
23  URPR11.SA               Alta
In [ ]:
# Tabela dinâmica com a contagem de alta e baixa
pivot_table = pd.pivot_table(df_resultados_candles, index=['Último Candlestick'], aggfunc='count')

# Renomeiar a coluna 'Ativo' para 'Contagem'
pivot_table = pivot_table.rename(columns={'Ativo': 'Contagem'})

# Imprimir a tabela dinâmica
print(pivot_table)
                    Contagem
Último Candlestick          
Alta                      16
Baixa                      8
In [ ]:
# Filtrar fundos com candlestick de alta (bullish)
fundos_candle_alta = df_candles[df_candles['Último Candlestick'] == 'Alta']

# Filtrar fundos com candlestick de baixa (bearish)
fundos_candle_baixa = df_candles[df_candles['Último Candlestick'] == 'Baixa']

# Imprimir a lista de fundos com candlestick de alta
print("Fundos com Candlestick de Alta:")
print(fundos_candle_alta['Ativo'].tolist())

# Imprimir a lista de fundos com candlestick de baixa
print("\nFundos com Candlestick de Baixa:")
print(fundos_candle_baixa['Ativo'].tolist())
Fundos com Candlestick de Alta:
['RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'HABT11.SA', 'TGAR11.SA', 'RECR11.SA', 'PLCR11.SA', 'HGBS11.SA', 'JPPA11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'URPR11.SA']

Fundos com Candlestick de Baixa:
['VGIP11.SA', 'RBOP11.SA', 'MGHT11.SA', 'KIVO11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'KNRE11.SA']

RSI¶

O RSI varia de 0 a 100. Tradicionalmente, o RSI é considerado sobrecomprado quando acima de 70 e sobrevendido quando abaixo de 30. Valores acima de 70 podem indicar que o ativo está em um estado de sobrecompra, o que poderia levar a uma reversão de preço em breve. Valores abaixo de 30 podem indicar que o ativo está em um estado de sobrevenda, o que poderia levar a uma reversão de preço para cima em breve.

In [ ]:
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

def calculo_rsi(dados, tempo):
    delta = dados.diff()
    up, down = delta.copy(), delta.copy()

    up[up < 0] = 0
    down[down > 0] = 0

    roll_up = up.rolling(window=tempo).mean()
    roll_down = down.abs().rolling(window=tempo).mean()

    rs = roll_up / roll_down
    rsi = 100 - (100 / (1 + rs))

    return rsi

resultados_rsi = []

for i, ativo in enumerate(ativos):
    df = yf.download(ativo, start='2023-09-01', end='2023-10-01')
    df['RSI'] = calculo_rsi(df['Close'], 14)
    ultimo_rsi = df['RSI'].iloc[-1]

    if ultimo_rsi < 30:
        estado_rsi = 'Sobrevenda (RSI < 30)'
    elif ultimo_rsi > 70:
        estado_rsi = 'Sobrecompra (RSI > 70)'
    else:
        estado_rsi = '30 <= RSI <= 70'

    resultados_rsi.append({'Ativo': ativo, 'Estado RSI': estado_rsi})

# Criando um DataFrame com os resultados
df_rsi = pd.DataFrame(resultados_rsi)
print(df_rsi)
   
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
        Ativo              Estado RSI
0   VGIP11.SA   Sobrevenda (RSI < 30)
1   RBRF11.SA         30 <= RSI <= 70
2   KFOF11.SA         30 <= RSI <= 70
3   PVBI11.SA         30 <= RSI <= 70
4   MFII11.SA         30 <= RSI <= 70
5   HGCR11.SA  Sobrecompra (RSI > 70)
6   RBOP11.SA         30 <= RSI <= 70
7   HABT11.SA         30 <= RSI <= 70
8   TGAR11.SA  Sobrecompra (RSI > 70)
9   MGHT11.SA   Sobrevenda (RSI < 30)
10  RECR11.SA         30 <= RSI <= 70
11  PLCR11.SA         30 <= RSI <= 70
12  KIVO11.SA         30 <= RSI <= 70
13  HGBS11.SA         30 <= RSI <= 70
14  JPPA11.SA         30 <= RSI <= 70
15  VOTS11.SA         30 <= RSI <= 70
16  XPSF11.SA         30 <= RSI <= 70
17  RBRL11.SA         30 <= RSI <= 70
18  BRCO11.SA         30 <= RSI <= 70
19  RZTR11.SA         30 <= RSI <= 70
20  JSRE11.SA         30 <= RSI <= 70
21  RZAK11.SA         30 <= RSI <= 70
22  KNRE11.SA         30 <= RSI <= 70
23  URPR11.SA         30 <= RSI <= 70
In [ ]:
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

for i, ativo in enumerate(ativos):
    df = yf.download(ativo, start='2023-09-01', end='2023-10-01')
    df['RSI'] = calculo_rsi(df['Close'], 14)

    fig = go.Figure()

    fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], mode='lines', name='RSI', line=dict(width=1.5)))
    
    # Adiciona uma linha com o preço do ativo
    fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Preço', line=dict(width=1.5, color='black')))

    fig.update_layout(title=f"RSI e Preço para {ativo}",
                      yaxis_title="RSI / Preço",
                      xaxis_rangeslider_visible=False,
                      yaxis_fixedrange=False)
    
    # Ajusta a frequência dos rótulos de data no eixo x
    fig.update_xaxes(
        tickangle=-45,  # Ângulo de rotação dos rótulos para melhor legibilidade
        dtick='M1',  # Exibe rótulos de data mensais
        tickformat='%Y-%m'  # Formato da data
    )

    fig.show()
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
In [ ]:
# Filtrar fundos com sobrevenda 

df_rsi_sobrevenda = df_rsi[df_rsi['Estado RSI'] == 'Sobrevenda (RSI < 30)']

# Imprimir a lista de fundos com sobrevenda
print("Fundos com sobrevenda:")
print(df_rsi_sobrevenda['Ativo'].tolist())

# Filtrar fundos com sobrecompra
df_rsi_sobrecompra = df_rsi[df_rsi['Estado RSI'] == 'Sobrecompra (RSI > 70)']

# Imprimir a lista de fundos com sobrecompra
print("\nFundos com sobrecompra:")
print(df_rsi_sobrecompra['Ativo'].tolist())
Fundos com sobrevenda:
['VGIP11.SA', 'MGHT11.SA']

Fundos com sobrecompra:
['HGCR11.SA', 'TGAR11.SA']

MACD¶

Cruzamento da Linha MACD e Linha de Sinal: Quando a linha MACD cruza acima da linha de sinal, é um sinal de compra, o que indica uma possível reversão de tendência de baixa para alta. Por outro lado, quando a linha MACD cruza abaixo da linha de sinal, é um sinal de venda, o que indica uma possível reversão de tendência de alta para baixa.

In [ ]:
# Função para o cálculo para o MACD
def calculo_macd(dados):
    short_window = 12
    long_window = 26
    signal_window = 9

    # ewm do pandas para o cálculo da média móvel exponencialmente ponderada
    short_media = dados.ewm(span=short_window, adjust=False).mean()
    long_media = dados.ewm(span=long_window, adjust=False).mean()

    macd = short_media - long_media
    signal = macd.ewm(span=signal_window, adjust=False).mean()

    return macd, signal

for ativo in ativos:
    df = yf.download(ativo, start='2023-09-01', end='2023-10-02')
    df['MACD'], df['Signal'] = calculo_macd(df['Close'])

    fig = go.Figure()

    fig.add_trace(go.Scatter(x=df.index, y=df['MACD'], mode='lines', name='MACD', line=dict(width=1.5)))
    fig.add_trace(go.Scatter(x=df.index, y=df['Signal'], mode='lines', name='Signal', line=dict(width=1.5, dash='dash')))
    fig.update_layout(title=f"MACD para {ativo}",
                      yaxis_title="MACD",
                      xaxis_rangeslider_visible=False,
                      yaxis_fixedrange=False)

    fig.show()
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed
[*********************100%***********************]  1 of 1 completed

Fundos com MACD no cruzamento de alta: MFII11.SA, HGCR11.SA, TGAR11.SA, PLCR11.SA, KIVO11.SA, HGBS11.SA, VOTS11.SA, RZTR11.SA, KNRE11.SA

Fundos com MACD no cruzamento de baixa: VGIP11.SA, RBRF11.SA, KFOF11.SA, PVBI11.SA, RBOP11.SA, HABT11.SA, MGHT11.SA, RECR11.SA, JPPA11.SA, XPSF11.SA, RBRL11.SA, BRCO11.SA, JSRE11.SA, RZKA11.SA, URPR11.SA

Correlações¶

In [ ]:
# Lista de ativos
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

# Baixar cotações de setembro de 2023
data = yf.download(ativos, start="2023-09-01", end="2023-10-02")['Adj Close']

# Análise da Correlação
matriz_correl = data.corr()

plt.figure(figsize=(12, 10))

# Heatmap da matriz de correlação
sns.heatmap(matriz_correl, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Heatmap da Matriz de Correlação')
plt.tight_layout()
plt.show()
[*********************100%***********************]  24 of 24 completed
No description has been provided for this image

Retornos dos Ativos¶

In [ ]:
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

# Inicia o DataFrame vazio para armezenar os retornos dos ativos
retorno = pd.DataFrame()

# Retorno do mês de setembro
for ativo in ativos:
    data = yf.Ticker(ativo)
    start_date = "2023-09-01"
    end_date = "2023-10-02"

    # DataFrame data que contém os preços de fechamento diários dos ativos
    data = data.history(start=start_date, end=end_date)

    # Função pct.change calcula os retornos percentuais diários do ativo
    data['Retorno'] = data['Close'].pct_change()

    # adicionar os retornos no DataFrame geral
    retorno[ativo] = data['Retorno']

# Remove as linhas que contêm valores ausentes (NAs)
retorno = retorno.dropna()

print(retorno)
                           VGIP11.SA  RBRF11.SA  KFOF11.SA  PVBI11.SA  \
Date                                                                    
2023-01-03 00:00:00-03:00   0.000928   0.010753   0.017371  -0.019569   
2023-01-04 00:00:00-03:00  -0.003130  -0.011348   0.000529  -0.005784   
2023-01-05 00:00:00-03:00   0.000116   0.000718   0.017992   0.021444   
2023-01-06 00:00:00-03:00  -0.000465  -0.002724   0.013645  -0.013400   
2023-01-09 00:00:00-03:00   0.006863  -0.012363  -0.019231  -0.013582   
...                              ...        ...        ...        ...   
2023-09-25 00:00:00-03:00  -0.001129  -0.041036  -0.038415   0.000000   
2023-09-26 00:00:00-03:00  -0.007119  -0.014549   0.004057  -0.003585   
2023-09-27 00:00:00-03:00  -0.001480   0.000124  -0.029945  -0.001610   
2023-09-28 00:00:00-03:00   0.000342  -0.011289  -0.001282  -0.017259   
2023-09-29 00:00:00-03:00  -0.004102   0.007779   0.051230   0.033388   

                           MFII11.SA  HGCR11.SA  RBOP11.SA  HABT11.SA  \
Date                                                                    
2023-01-03 00:00:00-03:00   0.000870   0.029520  -0.001546   0.002125   
2023-01-04 00:00:00-03:00   0.005974  -0.000291  -0.006452   0.013506   
2023-01-05 00:00:00-03:00   0.002915  -0.010950   0.000000  -0.002313   
2023-01-06 00:00:00-03:00   0.004091  -0.001568  -0.006493   0.001987   
2023-01-09 00:00:00-03:00   0.012651   0.000393  -0.040817  -0.015313   
...                              ...        ...        ...        ...   
2023-09-25 00:00:00-03:00  -0.000425  -0.000928   0.005559  -0.003638   
2023-09-26 00:00:00-03:00   0.006485  -0.001672  -0.008866  -0.012134   
2023-09-27 00:00:00-03:00  -0.005387   0.003071  -0.006735  -0.004348   
2023-09-28 00:00:00-03:00  -0.001593  -0.001763   0.023867   0.015284   
2023-09-29 00:00:00-03:00   0.004574   0.006877  -0.010033   0.007527   

                           TGAR11.SA  MGHT11.SA  ...  JPPA11.SA  VOTS11.SA  \
Date                                             ...                         
2023-01-03 00:00:00-03:00  -0.018519   0.026253  ...  -0.001824   0.057895   
2023-01-04 00:00:00-03:00  -0.005086  -0.002147  ...   0.000577  -0.042278   
2023-01-05 00:00:00-03:00  -0.010472   0.003944  ...  -0.005382   0.005518   
2023-01-06 00:00:00-03:00   0.002333   0.017857  ...  -0.000193   0.000000   
2023-01-09 00:00:00-03:00  -0.001496   0.000526  ...   0.000193   0.016463   
...                              ...        ...  ...        ...        ...   
2023-09-25 00:00:00-03:00   0.001202  -0.032623  ...   0.000605  -0.002020   
2023-09-26 00:00:00-03:00   0.001601  -0.000339  ...  -0.002218  -0.021548   
2023-09-27 00:00:00-03:00   0.004794  -0.011527  ...  -0.001313   0.015574   
2023-09-28 00:00:00-03:00  -0.001193   0.010461  ...  -0.001517  -0.000240   
2023-09-29 00:00:00-03:00   0.020621  -0.002037  ...   0.007092  -0.009946   

                           XPSF11.SA  RBRL11.SA  BRCO11.SA  RZTR11.SA  \
Date                                                                    
2023-01-03 00:00:00-03:00   0.005548  -0.010104  -0.002501   0.000958   
2023-01-04 00:00:00-03:00   0.015172   0.002459  -0.012237  -0.000426   
2023-01-05 00:00:00-03:00  -0.009511  -0.002576  -0.019598   0.005854   
2023-01-06 00:00:00-03:00  -0.010974   0.002214   0.006732   0.001270   
2023-01-09 00:00:00-03:00   0.000000  -0.035007   0.004630   0.008243   
...                              ...        ...        ...        ...   
2023-09-25 00:00:00-03:00  -0.003521  -0.008023  -0.008743  -0.009358   
2023-09-26 00:00:00-03:00  -0.005889   0.005464  -0.009535   0.000508   
2023-09-27 00:00:00-03:00  -0.018957  -0.002174  -0.001765  -0.014416   
2023-09-28 00:00:00-03:00   0.007246  -0.005447  -0.007474   0.024928   
2023-09-29 00:00:00-03:00  -0.002398   0.006572   0.007935   0.013467   

                           JSRE11.SA  RZAK11.SA  KNRE11.SA  URPR11.SA  
Date                                                                   
2023-01-03 00:00:00-03:00  -0.005105   0.021979  -0.016949  -0.006558  
2023-01-04 00:00:00-03:00  -0.003991   0.002379  -0.068965   0.005078  
2023-01-05 00:00:00-03:00   0.008300   0.003460   0.018519   0.000909  
2023-01-06 00:00:00-03:00   0.000426  -0.012218   0.036364   0.002120  
2023-01-09 00:00:00-03:00  -0.023975   0.014963  -0.017544   0.000705  
...                              ...        ...        ...        ...  
2023-09-25 00:00:00-03:00  -0.006910  -0.002710  -0.018182  -0.004174  
2023-09-26 00:00:00-03:00  -0.014302   0.002500   0.000000  -0.002042  
2023-09-27 00:00:00-03:00  -0.005621  -0.000325   0.018519  -0.003985  
2023-09-28 00:00:00-03:00  -0.008808   0.003796   0.000000   0.001189  
2023-09-29 00:00:00-03:00   0.007427   0.007888  -0.018182   0.012419  

[187 rows x 24 columns]
In [ ]:
def calcula_estat(column):
    return pd.Series({
        'Média': column.mean(),
        'Mediana': column.median(),
        'Desvio Padrão (populacional)': column.std(ddof=0),
        'Desvio Padrão (amostral)': column.std(),
        'Variância (populacional)': column.var(ddof=0),
        'Variância (amostral)': column.var(),
        'Coeficiente de Variação': (column.std() / column.mean())  if column.mean() != 0 else 0
    })

estatisticas_retorno = retorno.select_dtypes(include=['float64']).apply(calcula_estat)

estatisticas_retorno
Out[ ]:
VGIP11.SA RBRF11.SA KFOF11.SA PVBI11.SA MFII11.SA HGCR11.SA RBOP11.SA HABT11.SA TGAR11.SA MGHT11.SA ... JPPA11.SA VOTS11.SA XPSF11.SA RBRL11.SA BRCO11.SA RZTR11.SA JSRE11.SA RZAK11.SA KNRE11.SA URPR11.SA
Média 0.000502 0.001248 0.001988 0.001157 0.000665 0.000916 -0.003191 0.000844 0.000510 0.001016 ... 0.000338 0.000745 0.001238 0.000997 0.001548 0.000701 0.000736 0.000100 0.000290 0.000083
Mediana 0.000371 0.001912 0.000923 0.000485 0.000472 0.000774 -0.001274 0.001056 0.000490 0.000691 ... 0.000393 0.000000 0.001261 0.000571 0.000848 0.001200 0.001292 0.000600 0.000000 0.000308
Desvio Padrão (populacional) 0.007650 0.012587 0.014055 0.009895 0.006820 0.005425 0.030379 0.007065 0.007940 0.011963 ... 0.005648 0.014110 0.008858 0.011291 0.010115 0.011879 0.010718 0.010685 0.039844 0.008102
Desvio Padrão (amostral) 0.007671 0.012621 0.014093 0.009922 0.006838 0.005440 0.030460 0.007084 0.007962 0.011995 ... 0.005663 0.014148 0.008882 0.011321 0.010143 0.011911 0.010747 0.010713 0.039951 0.008124
Variância (populacional) 0.000059 0.000158 0.000198 0.000098 0.000047 0.000029 0.000923 0.000050 0.000063 0.000143 ... 0.000032 0.000199 0.000078 0.000127 0.000102 0.000141 0.000115 0.000114 0.001588 0.000066
Variância (amostral) 0.000059 0.000159 0.000199 0.000098 0.000047 0.000030 0.000928 0.000050 0.000063 0.000144 ... 0.000032 0.000200 0.000079 0.000128 0.000103 0.000142 0.000115 0.000115 0.001596 0.000066
Coeficiente de Variação 15.282803 10.115652 7.087718 8.576652 10.276403 5.936066 -9.545962 8.395039 15.606476 11.811250 ... 16.731192 19.002782 7.174043 11.351888 6.551122 16.990938 14.602920 107.182365 137.560767 97.640673

7 rows × 24 columns

Previsão de Preço usando Média Móvel¶

In [ ]:
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

window = 30

for ativo in ativos:
    data = yf.download(ativo, start="2023-01-01", end="2023-10-02")

    train_size = int(len(data) * 0.8)
    train = data['Close'][:train_size]
    test = data['Close'][train_size:]

    predictions = []

    for t in range(len(test)):
        if t < window:
            predictions.append(train[-(window-t):].mean())
        else:
            predictions.append(test[t-window:t].mean())

    rmse = sqrt(mean_squared_error(test[window:], predictions[window:]))
    print(f'Ativo: {ativo}, RMSE: {rmse}')

    plt.figure(figsize=(14,7))
    plt.plot(train.index, train, label='Treino')
    plt.plot(test.index, test, label='Real')
    plt.plot(test.index, predictions, label='Previsto')
    plt.legend(loc='best')
    plt.title(f"Previsão de Preço para {ativo} usando Média Móvel", fontsize=16)
    plt.xticks(fontsize=13)
    plt.yticks(fontsize=13)
    plt.legend(loc='upper left')
    plt.grid(True)
    #plt.show()
[*********************100%***********************]  1 of 1 completed
Ativo: VGIP11.SA, RMSE: 2.662621457553978
[*********************100%***********************]  1 of 1 completed
Ativo: RBRF11.SA, RMSE: 3.0509818657001526
[*********************100%***********************]  1 of 1 completed
Ativo: KFOF11.SA, RMSE: 2.3618002894888095
[*********************100%***********************]  1 of 1 completed
Ativo: PVBI11.SA, RMSE: 1.8435847416361784
[*********************100%***********************]  1 of 1 completed
Ativo: MFII11.SA, RMSE: 0.38624549006889647
[*********************100%***********************]  1 of 1 completed
Ativo: HGCR11.SA, RMSE: 0.921946284542225
[*********************100%***********************]  1 of 1 completed
Ativo: RBOP11.SA, RMSE: 12.53156084458245
[*********************100%***********************]  1 of 1 completed
Ativo: HABT11.SA, RMSE: 2.466854822568626
[*********************100%***********************]  1 of 1 completed
Ativo: TGAR11.SA, RMSE: 2.7261716980997037
[*********************100%***********************]  1 of 1 completed
Ativo: MGHT11.SA, RMSE: 4.5649820367351035
[*********************100%***********************]  1 of 1 completed
Ativo: RECR11.SA, RMSE: 1.503881774078767
[*********************100%***********************]  1 of 1 completed
Ativo: PLCR11.SA, RMSE: 0.8914985970114468
[*********************100%***********************]  1 of 1 completed
Ativo: KIVO11.SA, RMSE: 0.7532170206715817
[*********************100%***********************]  1 of 1 completed
Ativo: HGBS11.SA, RMSE: 1.9397436313267375
[*********************100%***********************]  1 of 1 completed
Ativo: JPPA11.SA, RMSE: 1.7897148559348275
[*********************100%***********************]  1 of 1 completed
Ativo: VOTS11.SA, RMSE: 0.9561584187717067
[*********************100%***********************]  1 of 1 completed
Ativo: XPSF11.SA, RMSE: 0.17905890053174656
[*********************100%***********************]  1 of 1 completed
Ativo: RBRL11.SA, RMSE: 1.2002321895826225
[*********************100%***********************]  1 of 1 completed
Ativo: BRCO11.SA, RMSE: 1.1463005565106712
[*********************100%***********************]  1 of 1 completed
Ativo: RZTR11.SA, RMSE: 1.7737150192635334
[*********************100%***********************]  1 of 1 completed
Ativo: JSRE11.SA, RMSE: 1.210701539364669
C:\Users\tatia\AppData\Local\Temp\ipykernel_28620\3387628264.py:23: RuntimeWarning:

More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.

[*********************100%***********************]  1 of 1 completed
Ativo: RZAK11.SA, RMSE: 0.35928084246809616
[*********************100%***********************]  1 of 1 completed
Ativo: KNRE11.SA, RMSE: 0.015721074734407706
[*********************100%***********************]  1 of 1 completed
Ativo: URPR11.SA, RMSE: 2.9514562758153784
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

Cluster¶

In [ ]:
ativos = ['VGIP11.SA', 'RBRF11.SA', 'KFOF11.SA', 'PVBI11.SA', 'MFII11.SA', 'HGCR11.SA', 'RBOP11.SA', 'HABT11.SA', 'TGAR11.SA', 'MGHT11.SA', 'RECR11.SA', 'PLCR11.SA', 'KIVO11.SA', 'HGBS11.SA', 'JPPA11.SA', 'VOTS11.SA', 'XPSF11.SA', 'RBRL11.SA', 'BRCO11.SA', 'RZTR11.SA', 'JSRE11.SA', 'RZAK11.SA', 'KNRE11.SA', 'URPR11.SA']

# Calcular WCSS para diferentes números de clusters
wcss = [] # armazenar uma lista para alocar as distâncias
for i in range(1, 11): # o 11 foi forçado, mas pode mudar.. np-completo... lembre-se
    kmeans = KMeans(n_clusters=i, n_init=10, random_state=42)
    kmeans.fit(matriz_correl)  # Usamos diretamente a matriz de correlação aqui
    wcss.append(kmeans.inertia_) ## resultados do inertia

# Plotar WCSS em relação ao número de clusters
plt.figure(figsize=(10,6))
plt.plot(range(1, 11), wcss, marker='o', linestyle='--')
plt.title('Método do Cotovelo')
plt.xlabel('Número de Clusters')
plt.ylabel('WCSS')
plt.grid(True)

plt.show()
No description has been provided for this image
In [ ]:
# Definir o número de clusters
num_clusters = 5

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=num_clusters)   # Rodar a função para o número de cluster definido
nomes = kmeans.fit_predict(matriz_correl)  # Alocar os tickers pela correlação


matriz_correl_clustered = matriz_correl.copy() # Copiar a matriz de correlação 
matriz_correl_clustered['Cluster'] = nomes # Adicionar nomes como uma nova coluna
matriz_correl_clustered = matriz_correl_clustered.sort_values('Cluster') # Ordenar as linhas pelos clusters

# Criar um DataFrame com os clusters
df_clusters = pd.DataFrame({
    'Ticker': matriz_correl.index,
    'Cluster': nomes
})

# Ordenar os clusters
df_clusters = df_clusters.sort_values(by='Cluster')
print(df_clusters)
       Ticker  Cluster
1   HABT11.SA        0
4   JPPA11.SA        0
21  VGIP11.SA        0
20  URPR11.SA        0
10  MGHT11.SA        0
13  RBOP11.SA        0
14  RBRF11.SA        0
18  RZTR11.SA        1
17  RZAK11.SA        1
12  PVBI11.SA        1
15  RBRL11.SA        1
11  PLCR11.SA        2
2   HGBS11.SA        2
3   HGCR11.SA        2
7   KIVO11.SA        2
19  TGAR11.SA        2
0   BRCO11.SA        3
6   KFOF11.SA        3
5   JSRE11.SA        3
16  RECR11.SA        3
23  XPSF11.SA        3
22  VOTS11.SA        4
9   MFII11.SA        4
8   KNRE11.SA        4
c:\Users\tatia\AppData\Local\Programs\Python\Python311\Lib\site-packages\sklearn\cluster\_kmeans.py:1412: FutureWarning:

The default value of `n_init` will change from 10 to 'auto' in 1.4. Set the value of `n_init` explicitly to suppress the warning

In [ ]:
# Heatmap da Matriz de Correlação com Clusters
plt.figure(figsize=(12, 10))
sns.heatmap(matriz_correl_clustered.drop('Cluster', axis=1), annot=True, cmap='Purples', vmin=-1, vmax=1, yticklabels=matriz_correl_clustered.index)
plt.title('Heatmap da Matriz de Correlação com Clusters')
plt.tight_layout()
plt.show()
No description has been provided for this image
In [ ]:
# Calcular os retornos diários e eliminar os valores ausentes
retorno = data.pct_change().dropna() # pct_change calcula os retornos percentuais diários
# Calcular o retorno acumulado
retorno_acumulado = (1 + retorno).cumprod()  
# Último valor do retorno acumulado
final_retorno_acumulado = retorno_acumulado.iloc[-1]

# Juntar os ativos com o retorno acumulado
df_combinado = pd.concat([df_clusters.set_index('Ticker'), final_retorno_acumulado], axis=1)
# Renomear as colunas
df_combinado.columns = ['Cluster', 'Retorno Acumulado']
# Ordenar os clusters
unique_clusters = df_clusters['Cluster'].unique() 

# Selecionar em cada cluster o ativo com maior retorno acumulado
tickers_selecionados = []
for cluster in unique_clusters:
    ticker = df_combinado[df_combinado['Cluster'] == cluster]['Retorno Acumulado'].idxmax()
    tickers_selecionados.append(ticker)

print("Fundos com maior retorno acumulado de cada cluster:")
for ticker in tickers_selecionados:
    print(ticker)
Fundos com maior retorno acumulado de cada cluster:
JPPA11.SA
RZTR11.SA
KFOF11.SA
MFII11.SA
TGAR11.SA
RECR11.SA
In [ ]:
# Calcular o retorno da carteira com todos os ativos
portfolio = data.pct_change().dropna().mean(axis=1)

# Calcular o retorno da carteira com os ativos com maior retorno 
dados_selecionados = data[tickers_selecionados]
weights = [1/len(tickers_selecionados)] * len(tickers_selecionados) #peso na carteira
portfolio_selecionado = dados_selecionados.pct_change().dropna().dot(weights) # o dot multiplica o valor do retorno pelo peso na carteira

# Calcular o retorno acumulado
retorno_acumulado_all = (1 + portfolio).cumprod()
retorno_acumulado_selected = (1 + portfolio_selecionado).cumprod()

# Plotar o retorno acumulado
plt.figure(figsize=(14, 7))
retorno_acumulado_all.plot(label="Carteira Todos os Tickers", legend=True)
retorno_acumulado_selected.plot(label="Carteira Diferenciada", legend=True)
plt.title('Comparação do Desempenho das Carteiras', fontsize=16)
plt.ylabel('Retorno Cumulativo', fontsize=13)
plt.xlabel('Data', fontsize=13)
plt.legend(loc='best')
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.grid(True)
plt.show()
No description has been provided for this image